package com.wingice.system.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wingice.common.page.EntityPageBean;
import com.wingice.common.page.PageBean;
import com.wingice.system.entity.SysDictionary;
import com.wingice.system.entity.SysDictionaryItem;
import com.wingice.system.mapper.SysDictionaryMapper;
import com.wingice.system.service.SysDictionaryItemService;
import com.wingice.system.service.SysDictionaryService;
import com.wingice.system.vo.dictionary.DictionaryView;
import com.wingice.system.vo.dictionary.SysDictionaryView;
import com.wingice.utils.transfer.TransferUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Transactional(rollbackFor = Exception.class)
@Service
public class SysDictionaryServiceImpl extends ServiceImpl<SysDictionaryMapper, SysDictionary> implements SysDictionaryService {
    /**
     * 系统类类型
     */
    final private static int SYSTEM_TYPE = 1;
    /**
     * 业务类类型
     */
    final private static int BUSINESS_TYPE = 2;
    @Resource
    private SysDictionaryItemService dictionaryItemService;

    @Override
    public Boolean deleteBatch(List<String> idList) {
        //删除字典项关联
        dictionaryItemService.remove(Wrappers.<SysDictionaryItem>lambdaQuery().in(SysDictionaryItem::getDictionaryId, idList));
        return removeByIds(idList);
    }

    @Override
    public Page<SysDictionaryView> page(EntityPageBean<SysDictionary> entityPageBean) {
        final Page<SysDictionary> page = page(new Page<SysDictionary>(entityPageBean.getPageObject().getPageNum(), entityPageBean.getPageObject().getPageSize())
                .addOrder(TransferUtils.transferOrderItem(entityPageBean.getPageObject().getAscs(), entityPageBean.getPageObject().getDescs())), Wrappers.<SysDictionary>lambdaQuery()
                .like(StringUtils.hasText(entityPageBean.getEntity().getDictionaryCode()), SysDictionary::getDictionaryCode, entityPageBean.getEntity().getDictionaryCode())
                .eq(entityPageBean.getEntity().getDictionaryType() != null, SysDictionary::getDictionaryType, entityPageBean.getEntity().getDictionaryType())
        );
        if (CollectionUtils.isEmpty(page.getRecords())) {
            return new Page<>();
        }
        final List<SysDictionaryItem> allSysDictionaryItemList = dictionaryItemService.list(Wrappers.<SysDictionaryItem>lambdaQuery().in(SysDictionaryItem::getDictionaryId, page.getRecords()
                .stream()
                .map(SysDictionary::getId)
                .collect(Collectors.toList())));
        final List<SysDictionaryView> sysDictionaryViewList = page.getRecords().stream().map(sysDictionary -> {
            final SysDictionaryView sysDictionaryView = new SysDictionaryView();
            BeanUtils.copyProperties(sysDictionary, sysDictionaryView);
            final List<SysDictionaryItem> sysDictionaryItemList = allSysDictionaryItemList.stream().filter(sysDictionaryItem -> sysDictionaryItem.getDictionaryId().equals(sysDictionary.getId())).collect(Collectors.toList());
            sysDictionaryView.setSysDictionaryItemList(sysDictionaryItemList);
            return sysDictionaryView;
        }).collect(Collectors.toList());
        return TransferUtils.transferPageInfo(page, sysDictionaryViewList);
    }

    @Override
    public List<SysDictionaryItem> getList(String code) {
        SysDictionary dictionary = getOne(Wrappers.lambdaQuery(SysDictionary.class).eq(SysDictionary::getDictionaryCode, code));
        if (ObjectUtil.isNull(dictionary)) {
            return new ArrayList<>();
        }
        return dictionaryItemService.list(Wrappers.lambdaQuery(SysDictionaryItem.class).eq(SysDictionaryItem::getDictionaryId, dictionary.getId()));
    }

    @Override
    public Map<String, List<SysDictionaryItem>> getListMap(List<String> codeList) {
        Map<String, List<SysDictionaryItem>> result = new HashMap<>(10);
        if (CollectionUtil.isEmpty(codeList)) {
            return result;
        }
        List<SysDictionary> dictionaryList = list(Wrappers.lambdaQuery(SysDictionary.class).in(SysDictionary::getDictionaryCode, codeList));
        List<String> dictionaryIdList = dictionaryList
                .stream()
                .map(SysDictionary::getId).collect(Collectors.toList());
        Map<String, List<SysDictionaryItem>> dictionaryItemMap = dictionaryItemService.list(Wrappers.lambdaQuery(SysDictionaryItem.class).in(SysDictionaryItem::getDictionaryId, dictionaryIdList))
                .stream().collect(Collectors.groupingBy(SysDictionaryItem::getDictionaryId));
        for (SysDictionary dictionary : dictionaryList) {
            List<SysDictionaryItem> dictionaryItemList = dictionaryItemMap.get(dictionary.getId());
            if (!CollectionUtil.isEmpty(dictionaryItemList)) {
                result.put(dictionary.getDictionaryCode(), dictionaryItemList);
            }
        }
        return result;
    }

    @Override
    public List<DictionaryView> getDictionaryList(String code) {
        return generateDictionaryList(code, false);
    }

    @Override
    public List<DictionaryView> getDictionaryList(String code, boolean reverse) {
        return generateDictionaryList(code, reverse);
    }

    @Override
    public Map<String, List<DictionaryView>> getDictionaryListMap(List<String> codeList) {
        return generateDictionaryViewListMap(codeList, false);
    }

    @Override
    public Map<String, List<DictionaryView>> getDictionaryListMap(List<String> codeList, boolean reverse) {
        return generateDictionaryViewListMap(codeList, reverse);
    }

    @Override
    public List<String> getDictionaryValueList(String code) {
        SysDictionary dictionary = getOne(Wrappers.lambdaQuery(SysDictionary.class).eq(SysDictionary::getDictionaryCode, code));
        if (ObjectUtil.isNull(dictionary)) {
            return new ArrayList<>();
        }
        return dictionaryItemService.list(Wrappers.lambdaQuery(SysDictionaryItem.class).eq(SysDictionaryItem::getDictionaryId, dictionary.getId())).stream().map(SysDictionaryItem::getItemName).collect(Collectors.toList());
    }

    @Override
    public Map<String, List<String>> getDictionaryValueListMap(List<String> codeList) {
        Map<String, List<String>> result = new HashMap<>(10);
        if (CollectionUtil.isEmpty(codeList)) {
            return new HashMap<>(10);
        }
        List<SysDictionary> dictionaryList = list(Wrappers.lambdaQuery(SysDictionary.class).in(SysDictionary::getDictionaryCode, codeList));
        List<String> dictionaryIdList = dictionaryList.stream().map(SysDictionary::getId).collect(Collectors.toList());
        Map<String, List<SysDictionaryItem>> dictionaryItemMap = dictionaryItemService.list(Wrappers.lambdaQuery(SysDictionaryItem.class).in(SysDictionaryItem::getDictionaryId, dictionaryIdList))
                .stream().collect(Collectors.groupingBy(SysDictionaryItem::getDictionaryId));

        for (SysDictionary dictionary : dictionaryList) {
            List<SysDictionaryItem> dictionaryItemList = dictionaryItemMap.get(dictionary.getId());
            if (!CollectionUtil.isEmpty(dictionaryItemList)) {
                result.put(dictionary.getDictionaryCode(), dictionaryItemList.stream().map(SysDictionaryItem::getItemName).collect(Collectors.toList()));
            }
        }
        return result;
    }

    @Override
    public Map<String, String> getDictionaryMap(String code) {
        return generateDictionaryMap(code, false);
    }

    @Override
    public Map<String, String> getDictionaryMap(String code, boolean reverse) {
        return generateDictionaryMap(code, reverse);
    }

    @Override
    public Map<String, Map<String, String>> getDictionaryMapMap(List<String> codeList) {
        return generateDictionaryMapMap(codeList, false);
    }

    @Override
    public Map<String, Map<String, String>> getDictionaryMapMap(List<String> codeList, boolean reverse) {
        return generateDictionaryMapMap(codeList, reverse);
    }

    @Override
    public List<SysDictionaryView> listAllDictionaryView(boolean reverse) {
        final EntityPageBean<SysDictionary> entityPageBean = new EntityPageBean<>();
        PageBean pageBean = new PageBean();
        pageBean.setPageNum(1L);
        pageBean.setPageSize(-1L);
        entityPageBean.setPageObject(pageBean);
        entityPageBean.setEntity(new SysDictionary());
        return page(entityPageBean).getRecords();
    }

    /**
     * 根据code 获得展示类列表
     *
     * @param code    字典code
     * @param reverse 是否反转
     * @return 字典信息展示对象集合
     * @date 2021/3/31 10:55
     */
    private Map<String, String> generateDictionaryMap(String code, boolean reverse) {
        Map<String, String> result = new HashMap<>();
        SysDictionary dictionary = getOne(Wrappers.lambdaQuery(SysDictionary.class).eq(SysDictionary::getDictionaryCode, code));
        if (ObjectUtil.isNull(dictionary)) {
            return result;
        }
        List<SysDictionaryItem> dictionaryItemList = dictionaryItemService.list(Wrappers.lambdaQuery(SysDictionaryItem.class).eq(SysDictionaryItem::getDictionaryId, dictionary.getId()));
        if (CollectionUtil.isEmpty(dictionaryItemList)) {
            return result;
        }
        if (SYSTEM_TYPE == dictionary.getDictionaryType()) {
            result = generateSystemMap(dictionaryItemList, reverse);
        }
        if (BUSINESS_TYPE == dictionary.getDictionaryType()) {
            result = generateBusinessMap(dictionaryItemList, reverse);
        }
        return result;
    }


    /**
     * 根据code 获得展示类列表
     *
     * @param code    字典code
     * @param reverse 是否反转
     * @return 字典信息展示对象集合
     * @date 2021/3/31 10:55
     */
    private List<DictionaryView> generateDictionaryList(String code, boolean reverse) {
        List<DictionaryView> result = new ArrayList<>();
        SysDictionary dictionary = getOne(Wrappers.lambdaQuery(SysDictionary.class).eq(SysDictionary::getDictionaryCode, code));
        if (ObjectUtil.isNull(dictionary)) {
            return result;
        }
        List<SysDictionaryItem> dictionaryItemList = dictionaryItemService.list(Wrappers.lambdaQuery(SysDictionaryItem.class).eq(SysDictionaryItem::getDictionaryId, dictionary.getId()));
        if (CollectionUtil.isEmpty(dictionaryItemList)) {
            return result;
        }
        if (SYSTEM_TYPE == dictionary.getDictionaryType()) {
            result = generateSystemViewList(dictionaryItemList, reverse);
        }
        if (BUSINESS_TYPE == dictionary.getDictionaryType()) {
            result = generateBusinessViewList(dictionaryItemList, reverse);
        }
        return result;
    }

    /**
     * 根据code 获得展示类列表Map
     *
     * @param codeList 字典code集合
     * @param reverse  是否反转 key value 互换
     * @return 字典信息展示对象集合Map
     * @date 2021/3/31 10:55
     */
    private Map<String, List<DictionaryView>> generateDictionaryViewListMap(List<String> codeList, boolean reverse) {
        Map<String, List<DictionaryView>> result = new HashMap<>(10);
        if (CollectionUtil.isEmpty(codeList)) {
            return result;
        }
        List<SysDictionary> dictionaryList = list(Wrappers.lambdaQuery(SysDictionary.class).in(SysDictionary::getDictionaryCode, codeList));
        if (CollectionUtil.isEmpty(dictionaryList)) {
            return result;
        }
        Map<Integer, List<SysDictionary>> dictionaryListMap = dictionaryList.stream().collect(Collectors.groupingBy(SysDictionary::getDictionaryType));
        if (CollectionUtil.isEmpty(dictionaryListMap)) {
            return result;
        }
        // 构造字典表 全部信息Map
        List<String> dictionaryIdList = dictionaryList.stream().map(SysDictionary::getId).collect(Collectors.toList());
        // key： dictionaryId value: 字典集合
        Map<String, List<SysDictionaryItem>> dictionaryItemListMap = dictionaryItemService.list(Wrappers.lambdaQuery(SysDictionaryItem.class).in(SysDictionaryItem::getDictionaryId, dictionaryIdList)).stream().collect(Collectors.groupingBy(SysDictionaryItem::getDictionaryId));
        // 分别处理普通类和业务类
        if (!ObjectUtil.isNull(dictionaryListMap.get(SYSTEM_TYPE))) {
            List<SysDictionary> sysDictionaryList = dictionaryListMap.get(SYSTEM_TYPE);
            for (SysDictionary dictionary : sysDictionaryList) {
                result.put(dictionary.getDictionaryCode(), generateSystemViewList(dictionaryItemListMap.get(dictionary.getId()), reverse));
            }
        }  // 分别处理普通类和业务类
        if (!ObjectUtil.isNull(dictionaryListMap.get(BUSINESS_TYPE))) {
            List<SysDictionary> sysDictionaryList = dictionaryListMap.get(BUSINESS_TYPE);
            for (SysDictionary dictionary : sysDictionaryList) {
                result.put(dictionary.getDictionaryCode(), generateBusinessViewList(dictionaryItemListMap.get(dictionary.getId()), reverse));
            }
        }
        return result;
    }

    /**
     * 根据code 获得展示类列表Map
     *
     * @param codeList 字典code集合
     * @param reverse  是否反转 key value 互换
     * @return 字典信息展示对象集合Map
     * @date 2021/3/31 10:55
     */
    private Map<String, Map<String, String>> generateDictionaryMapMap(List<String> codeList, boolean reverse) {
        Map<String, Map<String, String>> result = new HashMap<>(10);
        if (CollectionUtil.isEmpty(codeList)) {
            return result;
        }
        List<SysDictionary> dictionaryList = list(Wrappers.lambdaQuery(SysDictionary.class).in(SysDictionary::getDictionaryCode, codeList));
        if (CollectionUtil.isEmpty(dictionaryList)) {
            return result;
        }
        Map<Integer, List<SysDictionary>> dictionaryListMap = dictionaryList.stream().collect(Collectors.groupingBy(SysDictionary::getDictionaryType));
        if (CollectionUtil.isEmpty(dictionaryListMap)) {
            return result;
        }
        // 构造字典表 全部信息Map
        List<String> dictionaryIdList = dictionaryList.stream().map(SysDictionary::getId).collect(Collectors.toList());
        // key： dictionaryId value: 字典集合
        Map<String, List<SysDictionaryItem>> dictionaryItemListMap = dictionaryItemService.list(Wrappers.lambdaQuery(SysDictionaryItem.class).in(SysDictionaryItem::getDictionaryId, dictionaryIdList)).stream().collect(Collectors.groupingBy(SysDictionaryItem::getDictionaryId));
        // 分别处理普通类和业务类
        if (!ObjectUtil.isNull(dictionaryListMap.get(SYSTEM_TYPE))) {
            List<SysDictionary> sysDictionaryList = dictionaryListMap.get(SYSTEM_TYPE);
            for (SysDictionary dictionary : sysDictionaryList) {
                result.put(dictionary.getDictionaryCode(), generateSystemMap(dictionaryItemListMap.get(dictionary.getId()), reverse));
            }
        }  // 分别处理普通类和业务类
        if (!ObjectUtil.isNull(dictionaryListMap.get(BUSINESS_TYPE))) {
            List<SysDictionary> sysDictionaryList = dictionaryListMap.get(BUSINESS_TYPE);
            for (SysDictionary dictionary : sysDictionaryList) {
                result.put(dictionary.getDictionaryCode(), generateBusinessMap(dictionaryItemListMap.get(dictionary.getId()), reverse));
            }
        }
        return result;
    }


    /**
     * 构造系统展示对象
     * 不反转 id唯一
     * 反转 itemName唯一
     *
     * @param dictionaryItemList 待处理字典集合
     * @param reverse            是否反转 否(id: itemName) 是(itemName: id)
     * @date 2021/4/1 14:54
     */
    private List<DictionaryView> generateSystemViewList(List<SysDictionaryItem> dictionaryItemList, boolean reverse) {
        if (CollectionUtil.isEmpty(dictionaryItemList)) {
            return new ArrayList<>();
        }
        return dictionaryItemList.stream().map(item -> {
            DictionaryView dictionaryView = new DictionaryView();
            if (reverse) {
                dictionaryView.setKey(item.getItemName());
                dictionaryView.setValue(item.getId());
            } else {
                dictionaryView.setKey(item.getId());
                dictionaryView.setValue(item.getItemName());
            }

            return dictionaryView;
        }).collect(Collectors.toList());
    }

    /**
     * 构造业务展示对象
     * 不反转 code唯一
     * 反转 itemName唯一
     *
     * @param dictionaryItemList 待处理字典集合
     * @param reverse            是否反转 否(code: itemName) 是(itemName: code)
     * @date 2021/4/1 14:54
     */
    private List<DictionaryView> generateBusinessViewList(List<SysDictionaryItem> dictionaryItemList, boolean reverse) {
        if (CollectionUtil.isEmpty(dictionaryItemList)) {
            return new ArrayList<>();
        }
        return dictionaryItemList.stream().map(item -> {
            DictionaryView dictionaryView = new DictionaryView();
            if (reverse) {
                dictionaryView.setKey(item.getItemName());
                dictionaryView.setValue(item.getCode());
            } else {
                dictionaryView.setKey(item.getCode());
                dictionaryView.setValue(item.getItemName());
            }
            return dictionaryView;
        }).collect(Collectors.toList());
    }

    /**
     * 构造系统类字典项Map
     * 不反转 id唯一
     * 反转 itemName唯一
     *
     * @param dictionaryItemList 待处理字典集合
     * @param reverse            是否反转 否(id: itemName) 是(itemName: id)
     * @date 2021/4/1 14:54
     */
    private Map<String, String> generateSystemMap(List<SysDictionaryItem> dictionaryItemList, boolean reverse) {
        Map<String, String> result = new HashMap<>(10);
        if (CollectionUtil.isEmpty(dictionaryItemList)) {
            return result;
        }
        for (SysDictionaryItem item : dictionaryItemList) {
            if (reverse) {
                result.put(item.getItemName(), item.getCode());
            } else {
                result.put(item.getCode(), item.getItemName());
            }
        }
        return result;
    }

    /**
     * 构造业务类字典项Map
     * 不反转 code唯一
     * 反转 itemName唯一
     *
     * @param dictionaryItemList 待处理字典集合
     * @param reverse            是否反转 否(code: itemName) 是(itemName: code)
     * @date 2021/4/1 14:54
     */
    private Map<String, String> generateBusinessMap(List<SysDictionaryItem> dictionaryItemList, boolean reverse) {
        Map<String, String> result = new HashMap<>(10);
        if (CollectionUtil.isEmpty(dictionaryItemList)) {
            return result;
        }
        for (SysDictionaryItem item : dictionaryItemList) {
            if (reverse) {
                result.put(item.getItemName(), item.getId());
            } else {
                result.put(item.getId(), item.getItemName());
            }
        }
        return result;
    }
}

